# ui/components/point_editor.py
"""
点编辑器对话框组件 - 完整修复版本
负责点的详细编辑
"""

import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from typing import Dict, Any, Optional
import os

from core.point_manager import Point
from core.image_processor import ImageProcessor


class PointEditorDialog:
    """点编辑器对话框 - 完整修复版本"""

    def __init__(self, parent, point: Point, image_processor: ImageProcessor):
        self.parent = parent
        self.point = point
        self.image_processor = image_processor
        self.result = None

        # 创建对话框
        self.dialog = tk.Toplevel(parent)
        self.dialog.title("编辑点")
        self.dialog.geometry("500x500")
        self.dialog.resizable(False, False)
        self.dialog.transient(parent)
        self.dialog.grab_set()

        # 设置对话框位置（居中）
        self.dialog.update_idletasks()
        x = parent.winfo_x() + (parent.winfo_width() - self.dialog.winfo_width()) // 2
        y = parent.winfo_y() + (parent.winfo_height() - self.dialog.winfo_height()) // 2
        self.dialog.geometry(f"+{x}+{y}")

        # 创建界面
        self.create_widgets()

        # 绑定事件
        self.bind_events()

        # 加载点数据
        self.load_point_data()

    def create_widgets(self):
        """创建界面组件"""
        # 主框架
        main_frame = ttk.Frame(self.dialog, padding="15")
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 基本信息区域
        basic_frame = ttk.LabelFrame(main_frame, text="基本信息", padding="10")
        basic_frame.pack(fill=tk.X, pady=(0, 10))

        # 坐标信息
        coord_frame = ttk.Frame(basic_frame)
        coord_frame.pack(fill=tk.X, pady=5)

        ttk.Label(coord_frame, text="坐标 X:").pack(side=tk.LEFT)
        self.x_var = tk.StringVar()
        x_entry = ttk.Entry(coord_frame, textvariable=self.x_var, width=8)
        x_entry.pack(side=tk.LEFT, padx=5)

        ttk.Label(coord_frame, text="Y:").pack(side=tk.LEFT)
        self.y_var = tk.StringVar()
        y_entry = ttk.Entry(coord_frame, textvariable=self.y_var, width=8)
        y_entry.pack(side=tk.LEFT, padx=5)

        # 测试坐标按钮
        ttk.Button(
            coord_frame,
            text="测试坐标",
            command=self.test_coordinates,
            width=10
        ).pack(side=tk.RIGHT)

        # 启用状态
        self.enabled_var = tk.BooleanVar(value=True)
        ttk.Checkbutton(
            basic_frame, 
            text="启用此点",
            variable=self.enabled_var
        ).pack(anchor=tk.W, pady=5)

        # 操作配置区域
        action_frame = ttk.LabelFrame(main_frame, text="操作配置", padding="10")
        action_frame.pack(fill=tk.X, pady=(0, 10))

        # 点击类型
        click_frame = ttk.Frame(action_frame)
        click_frame.pack(fill=tk.X, pady=5)

        ttk.Label(click_frame, text="点击类型:").pack(side=tk.LEFT)
        self.click_type_var = tk.StringVar(value="单击")
        
        click_types = ["单击", "双击", "右键点击"]
        click_combo = ttk.Combobox(
            click_frame,
            textvariable=self.click_type_var,
            values=click_types,
            state="readonly",
            width=15
        )
        click_combo.pack(side=tk.LEFT, padx=5)

        # 延迟设置
        delay_frame = ttk.Frame(action_frame)
        delay_frame.pack(fill=tk.X, pady=5)

        ttk.Label(delay_frame, text="点击后延迟(秒):").pack(side=tk.LEFT)
        self.delay_after_var = tk.StringVar(value="0.5")
        delay_entry = ttk.Entry(delay_frame, textvariable=self.delay_after_var, width=8)
        delay_entry.pack(side=tk.LEFT, padx=5)

        # 输入内容区域
        input_frame = ttk.LabelFrame(main_frame, text="输入内容", padding="10")
        input_frame.pack(fill=tk.X, pady=(0, 10))

        # 输入方式选择
        input_method_frame = ttk.Frame(input_frame)
        input_method_frame.pack(fill=tk.X, pady=5)

        ttk.Label(input_method_frame, text="输入方式:").pack(side=tk.LEFT)
        self.input_method_var = tk.StringVar(value="text")
        
        input_methods = [
            ("文本输入", "text"),
            ("图片输入", "image")
        ]
        
        for text, value in input_methods:
            ttk.Radiobutton(
                input_method_frame, 
                text=text, 
                variable=self.input_method_var, 
                value=value,
                command=self.on_input_method_changed
            ).pack(side=tk.LEFT, padx=5)

        # 文本输入区域
        self.text_frame = ttk.Frame(input_frame)
        self.text_frame.pack(fill=tk.X, pady=5)

        ttk.Label(self.text_frame, text="输入文本:").pack(anchor=tk.W)
        self.text_var = tk.StringVar()
        self.text_entry = tk.Text(self.text_frame, height=4, width=50)
        text_scrollbar = ttk.Scrollbar(self.text_frame, orient=tk.VERTICAL, command=self.text_entry.yview)
        self.text_entry.configure(yscrollcommand=text_scrollbar.set)
        
        self.text_entry.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        text_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 图片输入区域
        self.image_frame = ttk.Frame(input_frame)
        
        ttk.Label(self.image_frame, text="图片文件:").pack(anchor=tk.W)
        
        image_path_frame = ttk.Frame(self.image_frame)
        image_path_frame.pack(fill=tk.X, pady=5)
        
        self.image_path_var = tk.StringVar()
        image_path_entry = ttk.Entry(image_path_frame, textvariable=self.image_path_var)
        image_path_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 5))
        
        ttk.Button(
            image_path_frame,
            text="选择图片",
            command=self.select_image,
            width=10
        ).pack(side=tk.RIGHT)

        # 图片预览
        self.preview_frame = ttk.Frame(self.image_frame)
        self.preview_frame.pack(fill=tk.X, pady=5)
        
        self.preview_label = ttk.Label(self.preview_frame, text="暂无预览")
        self.preview_label.pack()

        # 描述信息区域
        desc_frame = ttk.LabelFrame(main_frame, text="描述信息", padding="10")
        desc_frame.pack(fill=tk.X, pady=(0, 10))

        self.desc_var = tk.StringVar()
        desc_entry = ttk.Entry(desc_frame, textvariable=self.desc_var)
        desc_entry.pack(fill=tk.X, pady=5)

        # 按钮区域
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=tk.X, pady=(10, 0))

        ttk.Button(
            button_frame, 
            text="确定", 
            command=self.on_ok,
            style="Accent.TButton"
        ).pack(side=tk.RIGHT, padx=5)

        ttk.Button(
            button_frame, 
            text="取消", 
            command=self.dialog.destroy
        ).pack(side=tk.RIGHT)

        # 验证按钮
        ttk.Button(
            button_frame,
            text="验证点",
            command=self.validate_point
        ).pack(side=tk.LEFT)

        # 初始化输入方式显示
        self.on_input_method_changed()

    def bind_events(self):
        """绑定事件"""
        self.dialog.bind('<Return>', lambda e: self.on_ok())
        self.dialog.bind('<Escape>', lambda e: self.dialog.destroy())

    def load_point_data(self):
        """加载点数据"""
        try:
            # 基本信息
            self.x_var.set(str(self.point.x))
            self.y_var.set(str(self.point.y))
            self.enabled_var.set(self.point.enabled)

            # 操作配置
            self.click_type_var.set(self.point.click_type)
            self.delay_after_var.set(str(self.point.delay_after))

            # 输入内容
            if self.point.is_image:
                self.input_method_var.set("image")
                self.image_path_var.set(self.point.text)
                self.load_image_preview()
            else:
                self.input_method_var.set("text")
                self.text_entry.delete(1.0, tk.END)
                self.text_entry.insert(1.0, self.point.text)

            # 描述信息
            self.desc_var.set(self.point.description)

            # 更新输入方式显示
            self.on_input_method_changed()

        except Exception as e:
            messagebox.showerror("错误", f"加载点数据失败: {e}", parent=self.dialog)

    def on_input_method_changed(self):
        """输入方式改变事件"""
        if self.input_method_var.get() == "image":
            # 显示图片输入，隐藏文本输入
            self.text_frame.pack_forget()
            self.image_frame.pack(fill=tk.X, pady=5)
        else:
            # 显示文本输入，隐藏图片输入
            self.image_frame.pack_forget()
            self.text_frame.pack(fill=tk.X, pady=5)

    def select_image(self):
        """选择图片"""
        file_path = filedialog.askopenfilename(
            title="选择图片文件",
            filetypes=[
                ("图片文件", "*.png *.jpg *.jpeg *.gif *.bmp"),
                ("所有文件", "*.*")
            ]
        )

        if file_path:
            self.image_path_var.set(file_path)
            self.load_image_preview()

    def load_image_preview(self):
        """加载图片预览"""
        file_path = self.image_path_var.get()
        if not file_path or not os.path.exists(file_path):
            self.preview_label.config(text="图片文件不存在")
            return

        try:
            # 加载图片
            if self.image_processor.load_image(file_path):
                preview_image = self.image_processor.get_preview_image(size=(100, 100))
                if preview_image:
                    self.preview_label.config(image=preview_image, text="")
                else:
                    self.preview_label.config(text="预览生成失败")
            else:
                self.preview_label.config(text="图片加载失败")

        except Exception as e:
            self.preview_label.config(text=f"预览失败: {str(e)}")

    def test_coordinates(self):
        """测试坐标"""
        try:
            x = int(self.x_var.get())
            y = int(self.y_var.get())
            
            import pyautogui
            # 移动鼠标到测试坐标
            pyautogui.moveTo(x, y, duration=0.5)
            messagebox.showinfo("测试坐标", f"鼠标已移动到坐标 ({x}, {y})", parent=self.dialog)
            
        except ValueError:
            messagebox.showerror("错误", "坐标必须是整数", parent=self.dialog)
        except Exception as e:
            messagebox.showerror("错误", f"测试坐标失败: {e}", parent=self.dialog)

    def validate_point(self):
        """验证点数据"""
        errors = []

        # 验证坐标
        try:
            x = int(self.x_var.get())
            y = int(self.y_var.get())
            
            if x < 0 or y < 0:
                errors.append("坐标不能为负数")
                
            # 验证坐标是否在屏幕范围内
            try:
                import pyautogui
                screen_width, screen_height = pyautogui.size()
                if x >= screen_width or y >= screen_height:
                    errors.append(f"坐标 ({x}, {y}) 超出屏幕范围 ({screen_width}x{screen_height})")
            except:
                pass  # 如果pyautogui不可用，跳过屏幕范围检查
                
        except ValueError:
            errors.append("坐标必须是整数")

        # 验证延迟时间
        try:
            delay = float(self.delay_after_var.get())
            if delay < 0 or delay > 60:
                errors.append("延迟时间必须在0-60秒之间")
        except ValueError:
            errors.append("延迟时间必须是数字")

        # 验证输入内容
        if self.input_method_var.get() == "image":
            if not self.image_path_var.get():
                errors.append("请选择图片文件")
            elif not os.path.exists(self.image_path_var.get()):
                errors.append("图片文件不存在")
        else:
            text = self.text_entry.get(1.0, tk.END).strip()
            if len(text) > 1000:
                errors.append("文本内容过长（最多1000字符）")

        # 验证描述
        description = self.desc_var.get()
        if len(description) > 200:
            errors.append("描述内容过长（最多200字符）")

        if errors:
            messagebox.showerror("验证失败", "\n".join(errors), parent=self.dialog)
            return False
        else:
            messagebox.showinfo("验证通过", "点数据验证通过", parent=self.dialog)
            return True

    def on_ok(self):
        """确定按钮处理"""
        if not self.validate_point():
            return

        try:
            # 构建更新数据
            update_data = {
                'x': int(self.x_var.get()),
                'y': int(self.y_var.get()),
                'enabled': self.enabled_var.get(),
                'click_type': self.click_type_var.get(),
                'delay_after': float(self.delay_after_var.get()),
                'description': self.desc_var.get()
            }

            # 设置输入内容
            if self.input_method_var.get() == "image":
                update_data['text'] = self.image_path_var.get()
                update_data['is_image'] = True
            else:
                update_data['text'] = self.text_entry.get(1.0, tk.END).strip()
                update_data['is_image'] = False

            self.result = update_data
            self.dialog.destroy()

        except Exception as e:
            messagebox.showerror("错误", f"保存点数据失败: {e}", parent=self.dialog)

    def show(self):
        """显示对话框"""
        self.dialog.wait_window()
        return self.result